﻿using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using TFSTools.TFSLibrary;
using TFSTools.TFSLibrary.TestManagement;

namespace TFSTools.TestManagement.TestCaseReview
{
    public class TestCaseDataContext : INotifyPropertyChanged
    {
        #region Data Members

        private TFSWorkItem workItem;
        private string[] userNames;

        #endregion

        #region Constructor

        public TestCaseDataContext(TFSTestCase testCase, TFSTestTeamProject teamProject)
        {
            this.TestTeamProject = teamProject;
            this.InitializeView(testCase, 0);
        }

        private void InitializeView(TFSTestCase testCase, int selectedIterationIndex)
        {
            this.TestCase = testCase;
            this.workItem = testCase.WorkItem;

            var settings = Properties.Settings.Default;
            testCase.IncludeParameterNameInIterationText = settings.IncludeParameterNameInIterationText;
            testCase.IncludeDelimiterInIterationText = true;

            if (testCase.IterationData.Count > 0 && selectedIterationIndex >= 0)
            {
                testCase.SelectedIteration = testCase.IterationData[selectedIterationIndex];
            }

            this.TestActionList = new TestActionViewItemCollection(testCase.TestActionList, this);

            this.IsCommentsDirty = false;

            this.userNames = (from identity in testCase.Connection.GroupSecurity.GetUserIdentities()
                          select identity.DisplayName).ToArray();
        }
        
        #endregion

        #region Public Members

        public TFSTestCase TestCase { get; private set; }

        public TFSTestTeamProject TestTeamProject { get; set; }

        public TestActionViewItemCollection TestActionList { get; set; }

        public bool IsCommentsDirty { get; set; }

        public bool IsTestCaseDirty
        {
            get { return this.IsCommentsDirty || this.TestCase.WorkItem.IsDirty; }
        }

        public string TestCaseId
        {
            get { return this.TestCase.Id.ToString(); }
        }

        public string TitleWithId
        {
            get { return string.Format("{0}: {1}", this.TestCase.Id, this.TestCase.Title); }
        }

        public bool? IncludeParameterNameInIterationText
        {
            get { return this.TestCase.IncludeParameterNameInIterationText; }
            set 
            {
                this.TestCase.IncludeParameterNameInIterationText = value == true;
                this.TestActionList.IterationUpdated();

                var settings = Properties.Settings.Default;
                settings.IncludeParameterNameInIterationText = value == true;
                settings.Save();
            }
        }

        public string State
        {
            get { return this.workItem.State; }
            set
            {
                this.workItem.State = value;
                this.OnPropertyChanged("Reason");
                this.OnPropertyChanged("AvailableReasons");
                this.OnPropertyChanged("IsStateChanged");
                this.OnPropertyChanged("IsStateTheSame");
            }
        }

        public string[] AvailableStates { get { return this.workItem.AvailableStates; } }

        public string Reason
        {
            get { return this.workItem.Reason; }
            set
            {
                this.workItem.Reason = value;
                this.OnPropertyChanged("Reason");
            }
        }

        public string[] AvailableReasons { get { return this.workItem.AvailableReasons; } }

        public bool IsStateChanged { get { return this.workItem.IsStateChanged; } }

        public bool IsStateTheSame { get { return !this.workItem.IsStateChanged; } }

        public string AssignedTo
        {
            get { return this.workItem.Fields[TFSCoreField.AssignedTo].ValueString; }
            set
            {
                this.workItem.Fields["Assigned To"].Value = value;
                this.OnPropertyChanged("AssignedTo");
            }
        }

        public string[] UserNames { get { return this.userNames; } }

        public TFSTestIterationRow SelectedIteration
        {
            get 
            { 
                return this.TestCase.SelectedIteration; 
            }

            set
            {
                this.TestCase.SelectedIteration = value;
                this.TestActionList.IterationUpdated();
                this.OnPropertyChanged("SelectedIteration");
                this.OnPropertyChanged("NextIterationExists");
                this.OnPropertyChanged("PreviousIterationExists");
            }
        }

        public TFSTestIterationRowCollection IterationData
        {
            get { return this.TestCase.IterationData; }
        }

        public void InsertComment()
        {
            this.TestActionList.ShowCommentsOnSelectedItems();
            this.IsCommentsDirty = true;
        }

        public void ClearAllComments()
        {
            this.TestActionList.ClearAllComments();
            this.IsCommentsDirty = true;
        }

        public void Refresh()
        {
            var selectedIndex = this.TestCase.IterationData.IndexOf(this.TestCase.SelectedIteration);

            this.InitializeView(this.TestTeamProject.GetTestCase(this.TestCase.Id), -1);
            this.OnPropertyChanged("TitleWithId");
            this.OnPropertyChanged("State");
            this.OnPropertyChanged("Reason");
            this.OnPropertyChanged("IterationData");

            this.SelectedIteration = this.TestCase.IterationData[selectedIndex];

            this.OnPropertyChanged("TestActionList");
        }

        public bool NextIterationExists
        {
            get
            {
                if (this.TestCase.SelectedIteration != null)
                {
                    return this.TestCase.SelectedIteration.Index < this.TestCase.IterationData.Count - 1;
                }
                else
                {
                    return false;
                }
            }
        }

        public void NextIteration()
        {
            if (this.NextIterationExists)
            {
                var index = this.TestCase.SelectedIteration.Index;
                this.SelectedIteration = this.TestCase.IterationData[++index];
            }
        }

        public bool PreviousIterationExists
        {
            get
            {
                if (this.TestCase.SelectedIteration != null)
                {
                    return this.TestCase.SelectedIteration.Index > 0;
                }
                else
                {
                    return false;
                }
            }
        }

        public void PreviousIteration()
        {
            if (this.PreviousIterationExists)
            {
                var index = this.TestCase.SelectedIteration.Index;
                this.SelectedIteration = this.TestCase.IterationData[--index];
            }
        }

        public void Save()
        {
            this.TestCase.Save();
            this.IsCommentsDirty = false;
        }

        #endregion

        #region OnPropertyChanged

        private void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}
